Resampling Grids

In [1]:
import numpy as np
import xarray as xr
import geoviews as gv
import datashader as dsh
from geoviews import opts

gv.extension('bokeh', 'matplotlib')

opts.defaults(
    opts.Image(width=600, height=400, colorbar=True),
    opts.Feature(apply_ranges=False),
    opts.QuadMesh(width=600, height=400, colorbar=True))

In geographical applications grids and meshes of different kinds are very common and for visualization and analysis it is often very important to be able to resample them in different ways. Regridding can refer both to upsampling and downsampling a grid or mesh, which is achieved through interpolation and aggregation.

Naive approaches to regridding treat the space as flat, which is often simpler but can also give less accurate results when working with a spherical space such as the earth. In this user guide we will summarize how to work with different grid types including rectilinear, curvilinear grids and trimeshes. Additionally we will discuss different approaches to regridding working based on the assumption of a flat earth (using datashader) and a spherical earth (xESMF).

Rectilinear grids

Rectilinear grids are one of the most standard formats and are defined by regularly sampled coordinates along the two axes. The air_temperature dataset provided by xarray and used throughout the GeoViews documentation provides a good example.

In [2]:
ds = xr.tutorial.open_dataset('air_temperature').load().isel(time=slice(0, 100))
ds
Out[2]:
Show/Hide data repr Show/Hide attributes
xarray.Dataset
    • lat: 25
    • lon: 53
    • time: 100
    • lat
      (lat)
      float32
      75.0 72.5 70.0 ... 20.0 17.5 15.0
      standard_name :
      latitude
      long_name :
      Latitude
      units :
      degrees_north
      axis :
      Y
      array([75. , 72.5, 70. , 67.5, 65. , 62.5, 60. , 57.5, 55. , 52.5, 50. , 47.5,
             45. , 42.5, 40. , 37.5, 35. , 32.5, 30. , 27.5, 25. , 22.5, 20. , 17.5,
             15. ], dtype=float32)
    • lon
      (lon)
      float32
      200.0 202.5 205.0 ... 327.5 330.0
      standard_name :
      longitude
      long_name :
      Longitude
      units :
      degrees_east
      axis :
      X
      array([200. , 202.5, 205. , 207.5, 210. , 212.5, 215. , 217.5, 220. , 222.5,
             225. , 227.5, 230. , 232.5, 235. , 237.5, 240. , 242.5, 245. , 247.5,
             250. , 252.5, 255. , 257.5, 260. , 262.5, 265. , 267.5, 270. , 272.5,
             275. , 277.5, 280. , 282.5, 285. , 287.5, 290. , 292.5, 295. , 297.5,
             300. , 302.5, 305. , 307.5, 310. , 312.5, 315. , 317.5, 320. , 322.5,
             325. , 327.5, 330. ], dtype=float32)
    • time
      (time)
      datetime64[ns]
      2013-01-01 ... 2013-01-25T18:00:00
      standard_name :
      time
      long_name :
      Time
      array(['2013-01-01T00:00:00.000000000', '2013-01-01T06:00:00.000000000',
             '2013-01-01T12:00:00.000000000', '2013-01-01T18:00:00.000000000',
             '2013-01-02T00:00:00.000000000', '2013-01-02T06:00:00.000000000',
             '2013-01-02T12:00:00.000000000', '2013-01-02T18:00:00.000000000',
             '2013-01-03T00:00:00.000000000', '2013-01-03T06:00:00.000000000',
             '2013-01-03T12:00:00.000000000', '2013-01-03T18:00:00.000000000',
             '2013-01-04T00:00:00.000000000', '2013-01-04T06:00:00.000000000',
             '2013-01-04T12:00:00.000000000', '2013-01-04T18:00:00.000000000',
             '2013-01-05T00:00:00.000000000', '2013-01-05T06:00:00.000000000',
             '2013-01-05T12:00:00.000000000', '2013-01-05T18:00:00.000000000',
             '2013-01-06T00:00:00.000000000', '2013-01-06T06:00:00.000000000',
             '2013-01-06T12:00:00.000000000', '2013-01-06T18:00:00.000000000',
             '2013-01-07T00:00:00.000000000', '2013-01-07T06:00:00.000000000',
             '2013-01-07T12:00:00.000000000', '2013-01-07T18:00:00.000000000',
             '2013-01-08T00:00:00.000000000', '2013-01-08T06:00:00.000000000',
             '2013-01-08T12:00:00.000000000', '2013-01-08T18:00:00.000000000',
             '2013-01-09T00:00:00.000000000', '2013-01-09T06:00:00.000000000',
             '2013-01-09T12:00:00.000000000', '2013-01-09T18:00:00.000000000',
             '2013-01-10T00:00:00.000000000', '2013-01-10T06:00:00.000000000',
             '2013-01-10T12:00:00.000000000', '2013-01-10T18:00:00.000000000',
             '2013-01-11T00:00:00.000000000', '2013-01-11T06:00:00.000000000',
             '2013-01-11T12:00:00.000000000', '2013-01-11T18:00:00.000000000',
             '2013-01-12T00:00:00.000000000', '2013-01-12T06:00:00.000000000',
             '2013-01-12T12:00:00.000000000', '2013-01-12T18:00:00.000000000',
             '2013-01-13T00:00:00.000000000', '2013-01-13T06:00:00.000000000',
             '2013-01-13T12:00:00.000000000', '2013-01-13T18:00:00.000000000',
             '2013-01-14T00:00:00.000000000', '2013-01-14T06:00:00.000000000',
             '2013-01-14T12:00:00.000000000', '2013-01-14T18:00:00.000000000',
             '2013-01-15T00:00:00.000000000', '2013-01-15T06:00:00.000000000',
             '2013-01-15T12:00:00.000000000', '2013-01-15T18:00:00.000000000',
             '2013-01-16T00:00:00.000000000', '2013-01-16T06:00:00.000000000',
             '2013-01-16T12:00:00.000000000', '2013-01-16T18:00:00.000000000',
             '2013-01-17T00:00:00.000000000', '2013-01-17T06:00:00.000000000',
             '2013-01-17T12:00:00.000000000', '2013-01-17T18:00:00.000000000',
             '2013-01-18T00:00:00.000000000', '2013-01-18T06:00:00.000000000',
             '2013-01-18T12:00:00.000000000', '2013-01-18T18:00:00.000000000',
             '2013-01-19T00:00:00.000000000', '2013-01-19T06:00:00.000000000',
             '2013-01-19T12:00:00.000000000', '2013-01-19T18:00:00.000000000',
             '2013-01-20T00:00:00.000000000', '2013-01-20T06:00:00.000000000',
             '2013-01-20T12:00:00.000000000', '2013-01-20T18:00:00.000000000',
             '2013-01-21T00:00:00.000000000', '2013-01-21T06:00:00.000000000',
             '2013-01-21T12:00:00.000000000', '2013-01-21T18:00:00.000000000',
             '2013-01-22T00:00:00.000000000', '2013-01-22T06:00:00.000000000',
             '2013-01-22T12:00:00.000000000', '2013-01-22T18:00:00.000000000',
             '2013-01-23T00:00:00.000000000', '2013-01-23T06:00:00.000000000',
             '2013-01-23T12:00:00.000000000', '2013-01-23T18:00:00.000000000',
             '2013-01-24T00:00:00.000000000', '2013-01-24T06:00:00.000000000',
             '2013-01-24T12:00:00.000000000', '2013-01-24T18:00:00.000000000',
             '2013-01-25T00:00:00.000000000', '2013-01-25T06:00:00.000000000',
             '2013-01-25T12:00:00.000000000', '2013-01-25T18:00:00.000000000'],
            dtype='datetime64[ns]')
    • air
      (time, lat, lon)
      float32
      241.2 242.5 243.5 ... 295.4 294.9
      long_name :
      4xDaily Air temperature at sigma level 995
      units :
      degK
      precision :
      2
      GRIB_id :
      11
      GRIB_name :
      TMP
      var_desc :
      Air temperature
      dataset :
      NMC Reanalysis
      level_desc :
      Surface
      statistic :
      Individual Obs
      parent_stat :
      Other
      actual_range :
      [185.16 322.1 ]
      array([[[241.2    , 242.5    , 243.5    , ..., 232.79999, 235.5    ,
               238.59999],
              [243.79999, 244.5    , 244.7    , ..., 232.79999, 235.29999,
               239.29999],
              [250.     , 249.79999, 248.89   , ..., 233.2    , 236.39   ,
               241.7    ],
              ...,
              [296.6    , 296.19998, 296.4    , ..., 295.4    , 295.1    ,
               294.69998],
              [295.9    , 296.19998, 296.79   , ..., 295.9    , 295.9    ,
               295.19998],
              [296.29   , 296.79   , 297.1    , ..., 296.9    , 296.79   ,
               296.6    ]],
      
             [[242.09999, 242.7    , 243.09999, ..., 232.     , 233.59999,
               235.79999],
              [243.59999, 244.09999, 244.2    , ..., 231.     , 232.5    ,
               235.7    ],
              [253.2    , 252.89   , 252.09999, ..., 230.79999, 233.39   ,
               238.5    ],
              ...,
              [296.4    , 295.9    , 296.19998, ..., 295.4    , 295.1    ,
               294.79   ],
              [296.19998, 296.69998, 296.79   , ..., 295.6    , 295.5    ,
               295.1    ],
              [296.29   , 297.19998, 297.4    , ..., 296.4    , 296.4    ,
               296.6    ]],
      
             [[242.29999, 242.2    , 242.29999, ..., 234.29999, 236.09999,
               238.7    ],
              [244.59999, 244.39   , 244.     , ..., 230.29999, 232.     ,
               235.7    ],
              [256.19998, 255.5    , 254.2    , ..., 231.2    , 233.2    ,
               238.2    ],
              ...,
              [295.6    , 295.4    , 295.4    , ..., 296.29   , 295.29   ,
               295.     ],
              [296.19998, 296.5    , 296.29   , ..., 296.4    , 296.     ,
               295.6    ],
              [296.4    , 296.29   , 296.4    , ..., 297.     , 297.     ,
               296.79   ]],
      
             ...,
      
             [[252.79999, 253.59999, 253.79999, ..., 242.79999, 242.7    ,
               242.89   ],
              [250.89   , 251.29999, 251.09999, ..., 241.5    , 241.09999,
               241.79999],
              [245.29999, 245.     , 244.39   , ..., 239.59999, 240.89   ,
               243.39   ],
              ...,
              [296.     , 295.4    , 295.19998, ..., 294.     , 293.4    ,
               292.4    ],
              [297.     , 296.69998, 296.1    , ..., 293.9    , 293.6    ,
               292.9    ],
              [297.29   , 297.29   , 297.     , ..., 294.69998, 294.6    ,
               294.5    ]],
      
             [[251.79999, 252.89   , 253.5    , ..., 242.     , 242.     ,
               242.5    ],
              [254.2    , 254.29999, 253.7    , ..., 241.2    , 241.     ,
               241.89   ],
              [248.79999, 248.     , 246.7    , ..., 239.7    , 240.89   ,
               243.5    ],
              ...,
              [295.     , 294.     , 293.69998, ..., 294.19998, 293.5    ,
               292.69998],
              [296.19998, 295.69998, 295.1    , ..., 294.19998, 294.19998,
               293.29   ],
              [296.79   , 296.79   , 296.5    , ..., 295.1    , 295.     ,
               294.69998]],
      
             [[249.29999, 250.5    , 251.2    , ..., 240.59999, 240.7    ,
               241.29999],
              [252.89   , 254.09999, 254.5    , ..., 240.39   , 240.29999,
               241.29999],
              [250.7    , 250.59999, 250.     , ..., 238.7    , 240.     ,
               242.59999],
              ...,
              [295.9    , 294.5    , 294.5    , ..., 294.19998, 293.1    ,
               292.69998],
              [296.1    , 295.79   , 295.6    , ..., 294.6    , 294.29   ,
               293.9    ],
              [296.79   , 296.79   , 296.6    , ..., 295.79   , 295.4    ,
               294.9    ]]], dtype=float32)
  • Conventions :
    COARDS
    title :
    4x daily NMC reanalysis (1948)
    description :
    Data is from NMC initialized reanalysis (4x/day). These are the 0.9950 sigma level values.
    platform :
    Model
    references :
    http://www.esrl.noaa.gov/psd/data/gridded/data.ncep.reanalysis.html

As we already know from the Gridded Dataset sections, an xarray of this kind can easily be wrapped in a GeoViews dataset:

In [3]:
gvds = gv.Dataset(ds).redim.range(air=(230, 300))
gvds
Out[3]:
:Dataset   [lat,lon,time]   (air)

We can also easily plot this data by using the .to method to group the data into a set of Image elements indexed by 'time':

In [4]:
images = gvds.to(gv.Image, ['lon', 'lat'], dynamic=True)

It is important to note that if we look at the longitude coordinates above we can see that they are defined in the range (0, 360), while GeoViews generally expects it to be in the range (-180, 180). To correct this we can apply a simple fix:

In [5]:
ds['lon'] = np.where(ds.lon>180, ds.lon-360, ds.lon)

Now we are ready to display the data. Note that throughout this user guide we will be using Bokeh but we could easily switch to matplotlib if needed.

In [6]:
opts.defaults(opts.Image(cmap='viridis'))

images * gv.feature.coastline
Out[6]:

Datashader

HoloViews provides high-level wrappers around the datashader library, which make it possible to quickly resample or aggregate datasets of different kinds. Datashader knows nothing about non-flat coordinate systems, but provides a very fast, parallelized regridding operation for rectilinear grids. Here we will import the regrid operation and pass it our stack of images from above. While this dataset is fairly small and regridding will actually upsample the image to match the dimensions of the plot, regrid can very quickly downsample very large datasets.

One important thing to note about the resampling operations we will be working with in this user guide is that they are dynamic and linked to the plot dimensions and axis ranges. This means that whenever we zoom or pan the data will be resampled. If we want to disable this linked behavior and supply an explicit width and height we can disable the streams by passing streams=[] as a keyword argument.

In [7]:
from holoviews.operation.datashader import regrid
regrid(images) * gv.feature.coastline
Out[7]:

xESMF

The xESMF library is specifically designed to provide an easy way to accurately resample grids defined in geographic coordinate systems and differs significantly from the simpler approach used by datashader, which applies simple upsampling and downsampling. xESMF is a wrapper around the ESMF regridding algorithms, which compute an interpolation weight matrix which is applied to remap the values of the source grid onto the destination grid.

In GeoViews these algorithms are made available via the weighted_regrid operation, which supports the different interpolation modes including: 'bilinear', 'nearest_s2d', 'nearest_d2s' and 'conservative'. Since generating the sparse weight matrix takes much longer than applying it the operation will cache the weight matrix on disk for later use; this optimization can be disabled via the reuse_weights parameter or customized by defining a custom file_pattern.

In [8]:
from geoviews.operation.regrid import weighted_regrid
weighted_regrid(images) * gv.feature.coastline
Create weight file: bilinear_(-161.250, -28.750)_(13.750, 76.250)_400x400.nc
Out[8]:

Since this operation creates local weight files we will want to clean up after ourselves once we are done, to do so we can call the weighted_regrid.clean_weight_files method.

In [9]:
weighted_regrid.clean_weight_files()
Deleted 1 weight files

Onto an existing grid

The operation also allows us to define a target grid, which we can either define manually or by using a utility provided by the xESMF library. Here we will define a $2^{\circ}\times2^{\circ}$ grid.

In [10]:
import xesmf as xe
grid = xe.util.grid_2d(-160, -35, 2, 15, 70, 2)
grid
Out[10]:
Show/Hide data repr Show/Hide attributes
xarray.Dataset
    • x: 63
    • x_b: 64
    • y: 28
    • y_b: 29
    • lon
      (y, x)
      float64
      -159.0 -157.0 ... -37.0 -35.0
      array([[-159., -157., -155., ...,  -39.,  -37.,  -35.],
             [-159., -157., -155., ...,  -39.,  -37.,  -35.],
             [-159., -157., -155., ...,  -39.,  -37.,  -35.],
             ...,
             [-159., -157., -155., ...,  -39.,  -37.,  -35.],
             [-159., -157., -155., ...,  -39.,  -37.,  -35.],
             [-159., -157., -155., ...,  -39.,  -37.,  -35.]])
    • lat
      (y, x)
      float64
      16.0 16.0 16.0 ... 70.0 70.0 70.0
      array([[16., 16., 16., ..., 16., 16., 16.],
             [18., 18., 18., ..., 18., 18., 18.],
             [20., 20., 20., ..., 20., 20., 20.],
             ...,
             [66., 66., 66., ..., 66., 66., 66.],
             [68., 68., 68., ..., 68., 68., 68.],
             [70., 70., 70., ..., 70., 70., 70.]])
    • lon_b
      (y_b, x_b)
      int64
      -160 -158 -156 -154 ... -38 -36 -34
      array([[-160, -158, -156, ...,  -38,  -36,  -34],
             [-160, -158, -156, ...,  -38,  -36,  -34],
             [-160, -158, -156, ...,  -38,  -36,  -34],
             ...,
             [-160, -158, -156, ...,  -38,  -36,  -34],
             [-160, -158, -156, ...,  -38,  -36,  -34],
             [-160, -158, -156, ...,  -38,  -36,  -34]])
    • lat_b
      (y_b, x_b)
      int64
      15 15 15 15 15 ... 71 71 71 71 71
      array([[15, 15, 15, ..., 15, 15, 15],
             [17, 17, 17, ..., 17, 17, 17],
             [19, 19, 19, ..., 19, 19, 19],
             ...,
             [67, 67, 67, ..., 67, 67, 67],
             [69, 69, 69, ..., 69, 69, 69],
             [71, 71, 71, ..., 71, 71, 71]])

    Since the grid has 2D coordinate arrays the regridded data will be wrapped in and displayed as a QuadMesh:

    In [11]:
    target = gv.Dataset(grid, kdims=['lon', 'lat'])
    weighted_regrid(images, target=target, streams=[]) * gv.feature.coastline
    
    Create weight file: bilinear_(-159.000, -35.000)_(16.000, 70.000)_63x28.nc
    
    Out[11]:

    Curvilinear Grids

    Curvilinear grids are another very common mesh type, which are usually defined by multi-dimensional coordinate arrays:

    In [12]:
    ds = xr.tutorial.open_dataset('rasm').load()
    ds
    
    Out[12]:
    Show/Hide data repr Show/Hide attributes
    xarray.Dataset
      • time: 36
      • x: 275
      • y: 205
      • time
        (time)
        object
        1980-09-16 12:00:00 ... 1983-08-17 00:00:00
        long_name :
        time
        type_preferred :
        int
        array([cftime.DatetimeNoLeap(1980-09-16 12:00:00),
               cftime.DatetimeNoLeap(1980-10-17 00:00:00),
               cftime.DatetimeNoLeap(1980-11-16 12:00:00),
               cftime.DatetimeNoLeap(1980-12-17 00:00:00),
               cftime.DatetimeNoLeap(1981-01-17 00:00:00),
               cftime.DatetimeNoLeap(1981-02-15 12:00:00),
               cftime.DatetimeNoLeap(1981-03-17 00:00:00),
               cftime.DatetimeNoLeap(1981-04-16 12:00:00),
               cftime.DatetimeNoLeap(1981-05-17 00:00:00),
               cftime.DatetimeNoLeap(1981-06-16 12:00:00),
               cftime.DatetimeNoLeap(1981-07-17 00:00:00),
               cftime.DatetimeNoLeap(1981-08-17 00:00:00),
               cftime.DatetimeNoLeap(1981-09-16 12:00:00),
               cftime.DatetimeNoLeap(1981-10-17 00:00:00),
               cftime.DatetimeNoLeap(1981-11-16 12:00:00),
               cftime.DatetimeNoLeap(1981-12-17 00:00:00),
               cftime.DatetimeNoLeap(1982-01-17 00:00:00),
               cftime.DatetimeNoLeap(1982-02-15 12:00:00),
               cftime.DatetimeNoLeap(1982-03-17 00:00:00),
               cftime.DatetimeNoLeap(1982-04-16 12:00:00),
               cftime.DatetimeNoLeap(1982-05-17 00:00:00),
               cftime.DatetimeNoLeap(1982-06-16 12:00:00),
               cftime.DatetimeNoLeap(1982-07-17 00:00:00),
               cftime.DatetimeNoLeap(1982-08-17 00:00:00),
               cftime.DatetimeNoLeap(1982-09-16 12:00:00),
               cftime.DatetimeNoLeap(1982-10-17 00:00:00),
               cftime.DatetimeNoLeap(1982-11-16 12:00:00),
               cftime.DatetimeNoLeap(1982-12-17 00:00:00),
               cftime.DatetimeNoLeap(1983-01-17 00:00:00),
               cftime.DatetimeNoLeap(1983-02-15 12:00:00),
               cftime.DatetimeNoLeap(1983-03-17 00:00:00),
               cftime.DatetimeNoLeap(1983-04-16 12:00:00),
               cftime.DatetimeNoLeap(1983-05-17 00:00:00),
               cftime.DatetimeNoLeap(1983-06-16 12:00:00),
               cftime.DatetimeNoLeap(1983-07-17 00:00:00),
               cftime.DatetimeNoLeap(1983-08-17 00:00:00)], dtype=object)
      • xc
        (y, x)
        float64
        189.2 189.4 189.6 ... 17.15 16.91
        long_name :
        longitude of grid cell center
        units :
        degrees_east
        bounds :
        xv
        array([[189.22293223, 189.38990916, 189.55836619, ..., 293.77906088,
                294.0279241 , 294.27439931],
               [188.96836986, 189.13470591, 189.30253733, ..., 294.05584005,
                294.30444387, 294.55065969],
               [188.71234264, 188.87800731, 189.04515208, ..., 294.335053  ,
                294.58337453, 294.8292928 ],
               ...,
               [124.04724025, 123.88362026, 123.71852016, ...,  16.83171831,
                 16.58436953,  16.33949649],
               [123.78686428, 123.62254238, 123.45672512, ...,  17.11814486,
                 16.87043749,  16.62518298],
               [123.52798366, 123.36295986, 123.1964407 , ...,  17.40209947,
                 17.1540526 ,  16.90845095]])
      • yc
        (y, x)
        float64
        16.53 16.78 17.02 ... 27.76 27.51
        long_name :
        latitude of grid cell center
        units :
        degrees_north
        bounds :
        yv
        array([[16.53498637, 16.7784556 , 17.02222429, ..., 27.36301592,
                27.11811045, 26.87289026],
               [16.69397341, 16.93865381, 17.18364512, ..., 27.5847719 ,
                27.33821848, 27.0913656 ],
               [16.85219179, 17.09808909, 17.34430872, ..., 27.80584314,
                27.55764558, 27.30915621],
               ...,
               [17.31179033, 17.56124674, 17.81104646, ..., 28.4502485 ,
                28.19718339, 27.94384744],
               [17.15589701, 17.40414034, 17.65272318, ..., 28.23129632,
                27.97989251, 27.72821596],
               [16.99919497, 17.24622904, 17.49358736, ..., 28.01160028,
                27.76185586, 27.51182726]])
      • Tair
        (time, y, x)
        float64
        nan nan nan ... 28.66 28.19 28.21
        units :
        C
        long_name :
        Surface air temperature
        type_preferred :
        double
        time_rep :
        instantaneous
        array([[[        nan,         nan,         nan, ...,         nan,
                         nan,         nan],
                [        nan,         nan,         nan, ...,         nan,
                         nan,         nan],
                [        nan,         nan,         nan, ...,         nan,
                         nan,         nan],
                ...,
                [        nan,         nan,         nan, ..., 27.03290153,
                 27.03125761, 27.33531541],
                [        nan,         nan,         nan, ..., 27.2784053 ,
                 26.80261869, 27.08603517],
                [        nan,         nan,         nan, ..., 27.02344402,
                 26.56473862, 26.73064933]],
        
               [[        nan,         nan,         nan, ...,         nan,
                         nan,         nan],
                [        nan,         nan,         nan, ...,         nan,
                         nan,         nan],
                [        nan,         nan,         nan, ...,         nan,
                         nan,         nan],
                ...,
                [        nan,         nan,         nan, ..., 24.52606661,
                 24.44559149, 24.72489025],
                [        nan,         nan,         nan, ..., 24.81092341,
                 24.29623992, 24.61422421],
                [        nan,         nan,         nan, ..., 24.49876196,
                 24.29967705, 24.45439921]],
        
               [[        nan,         nan,         nan, ...,         nan,
                         nan,         nan],
                [        nan,         nan,         nan, ...,         nan,
                         nan,         nan],
                [        nan,         nan,         nan, ...,         nan,
                         nan,         nan],
                ...,
                [        nan,         nan,         nan, ..., 15.59297273,
                 15.29777668, 15.4266377 ],
                [        nan,         nan,         nan, ..., 16.00414707,
                 15.18088805, 15.50982104],
                [        nan,         nan,         nan, ..., 15.90243768,
                 15.54410181, 15.70258798]],
        
               ...,
        
               [[        nan,         nan,         nan, ...,         nan,
                         nan,         nan],
                [        nan,         nan,         nan, ...,         nan,
                         nan,         nan],
                [        nan,         nan,         nan, ...,         nan,
                         nan,         nan],
                ...,
                [        nan,         nan,         nan, ..., 28.24428726,
                 28.36994752, 28.72271671],
                [        nan,         nan,         nan, ..., 28.37887215,
                 28.04355761, 28.34557868],
                [        nan,         nan,         nan, ..., 27.98941074,
                 27.636075  , 27.7891351 ]],
        
               [[        nan,         nan,         nan, ...,         nan,
                         nan,         nan],
                [        nan,         nan,         nan, ...,         nan,
                         nan,         nan],
                [        nan,         nan,         nan, ...,         nan,
                         nan,         nan],
                ...,
                [        nan,         nan,         nan, ..., 27.8597472 ,
                 27.82928439, 28.09249224],
                [        nan,         nan,         nan, ..., 27.89704094,
                 27.31104941, 27.67387171],
                [        nan,         nan,         nan, ..., 27.46837113,
                 27.0088944 , 27.23017976]],
        
               [[        nan,         nan,         nan, ...,         nan,
                         nan,         nan],
                [        nan,         nan,         nan, ...,         nan,
                         nan,         nan],
                [        nan,         nan,         nan, ...,         nan,
                         nan,         nan],
                ...,
                [        nan,         nan,         nan, ..., 28.95929072,
                 28.87672039, 29.04890862],
                [        nan,         nan,         nan, ..., 29.036132  ,
                 28.42273578, 28.68721201],
                [        nan,         nan,         nan, ..., 28.66381585,
                 28.18595533, 28.20753022]]])
    • title :
      /workspace/jhamman/processed/R1002RBRxaaa01a/lnd/temp/R1002RBRxaaa01a.vic.ha.1979-09-01.nc
      institution :
      U.W.
      source :
      RACM R1002RBRxaaa01a
      output_frequency :
      daily
      output_mode :
      averaged
      convention :
      CF-1.4
      references :
      Based on the initial model of Liang et al., 1994, JGR, 99, 14,415- 14,429.
      comment :
      Output from the Variable Infiltration Capacity (VIC) model.
      nco_openmp_thread_number :
      1
      NCO :
      "4.6.0"
      history :
      Tue Dec 27 14:15:22 2016: ncatted -a dimensions,,d,, rasm.nc rasm.nc Tue Dec 27 13:38:40 2016: ncks -3 rasm.nc rasm.nc history deleted for brevity

    Just like the rectilinear grids GeoViews understands this kind of data natively. So we again wrap this dataset in a gv.Dataset and define a fixed range for the air teperature (Tair) values:

    In [13]:
    gvds = gv.Dataset(ds).redim.range(Tair=(-25, 25))
    gvds
    
    Out[13]:
    :Dataset   [time,xc,yc]   (Tair)

    Now we can plot this data directly as a gv.QuadMesh, however this is generally quite slow, especially when we are working with bokeh where each grid point is rendered as a distinct polygon. We will therefore downsample the data by a factor of 3 along both dimensions:

    In [14]:
    opts.defaults(opts.Image(cmap='RdBu_r'), opts.QuadMesh(cmap='RdBu_r'))
    
    quadmeshes = gvds.to(gv.QuadMesh, ['xc', 'yc'], dynamic=True)
    quadmeshes.apply(lambda x: x.clone(x.data.Tair[::3, ::3])) * gv.feature.coastline
    
    Out[14]:

    The problem is less severe when plotting using matplotlib but even then plotting can be fairly slow given a large enough mesh.

    In [15]:
    gv.output(quadmeshes.opts(cmap='RdBu_r') * gv.feature.coastline, backend='matplotlib', size=300)
    

    If we want to explore a very large grid it therefore often makes sense to resample the data onto a rectilinear grid, which can be rendered much more efficiently. Once again we have the option of using the datashader based approach or the more accurate xESMF based approach.

    Datashader

    To regrid a QuadMesh using GeoViews we can import the rasterize operation. In the background the operation will convert the QuadMesh into a TriMesh, which datashader understands. To optimize this conversion so it occurs only when aggregating the QuadMesh for the first time we can activate the precompute option. Additionally we have to define an aggregator, in this case to compute the mean Tair value in a pixel:

    In [16]:
    from holoviews.operation.datashader import rasterize
    rasterize(quadmeshes, precompute=True, aggregator=dsh.mean('Tair')) * gv.feature.coastline
    
    Out[16]:

    xESMF

    Now we will once again use the xESMF based regridding for which we can still use the weighted_regrid operation, since it supports both rectilinear and curvilinear grids. Since the original data doesn't have a very high resolution we will also disable the streams linking the operation to the plot dimensions and axis ranges.

    In [17]:
    from geoviews.operation.regrid import weighted_regrid
    weighted_regrid(quadmeshes, streams=[]) * gv.feature.coastline
    
    Create weight file: bilinear_(0.356, 449.650)_(16.334, 89.638)_400x400.nc
    
    Out[17]:

    Finally lets clean up after ourselves one last time:

    In [18]:
    weighted_regrid.clean_weight_files()
    
    Deleted 2 weight files
    

    Right click to download this notebook from GitHub.